/*
 * Register16 class wraps 16 bit registers
 * 16 bit registers are word compatible 
 * */

package cpu.datastores;

import cpu.datatypes.*;
import cpu.interfaces.Register;

public class Register16 extends Word implements Register {

	public int size( ) {
		return 16;
	}
	
	public int toSignedInteger( ) {
		// 2s complement
		
		boolean negative = false;

		int accumulator = 0;
		
		if( byteLow.bit( 0 ).value  ) {
			negative = true;
		}
		Word value;
		if( negative ) { 
			value = twoscomplement( );
		} else {
			value = new Word( this );
		}
		
		for( int i = 1; i < 8; i++ ) {
			if( value.byteLow.bit( i ).value )
				accumulator += java.lang.Math.pow( 2, i - 1 );
		}
		for( int i = 0; i < 8; i++ ) {
			if( value.byteHigh.bit( i ).value )
				accumulator += java.lang.Math.pow( 2, i - 1 + 8 );
		}
		
		if( negative ) accumulator = -accumulator;
		
		return accumulator;
	}
	public boolean fromSignedInteger( int n ) {
		// 2s complement
		
		boolean negative = false;
		
		int accumulator = n;
		
		if( accumulator < 0 ) {
			negative = true;
			accumulator = -accumulator;
		}
		
		for( int i = 7; i >= 0; i-- ) {
			if( accumulator / (int) java.lang.Math.pow( 2, i - 1 + 8 ) >= 1 ) {
				byteHigh.bit( i ).value = true;
				accumulator -= java.lang.Math.pow( 2, i - 1 + 8 );
			} else {
				byteHigh.bit( i ).value = false;
			}
		}
		for( int i = 7; i >= 1; i-- ) {
			if( accumulator / (int) java.lang.Math.pow( 2, i - 1 ) >= 1 ) {
				byteLow.bit( i ).value = true;
				accumulator -= java.lang.Math.pow( 2, i - 1 );
			} else {
				byteLow.bit( i ).value = false;
			}
		}

		if( negative ) {
			twoscomplementinline( );
			byteLow.bit( 0 ).value = true;				
		} else {
			byteLow.bit( 0 ).value = false;
		}

		if( accumulator != 0 ) 
			return true;		// overflow
		return false;			// no overflow
	}
	public boolean fromSignedInteger( cpu.datatypes.Integer n ) {
		// 2s complement
		
		boolean negative = false;
		
		int accumulator = n.toJavaInt( );
		
		if( accumulator < 0 ) {
			negative = true;
			accumulator = -accumulator;
		}
		
		for( int i = 7; i >= 0; i-- ) {
			if( accumulator / (int) java.lang.Math.pow( 2, i - 1 + 8 ) >= 1 ) {
				byteHigh.bit( i ).value = true;
				accumulator -= java.lang.Math.pow( 2, i - 1 + 8 );
			} else {
				byteHigh.bit( i ).value = false;
			}
		}
		for( int i = 7; i >= 1; i-- ) {
			if( accumulator / (int) java.lang.Math.pow( 2, i - 1 ) >= 1 ) {
				byteLow.bit( i ).value = true;
				accumulator -= java.lang.Math.pow( 2, i - 1 );
			} else {
				byteLow.bit( i ).value = false;
			}
		}

		if( negative ) {
			twoscomplementinline( );
			byteLow.bit( 0 ).value = true;				
		} else {
			byteLow.bit( 0 ).value = false;
		}

		if( accumulator != 0 ) 
			return true;		// overflow
		return false;			// no overflow
	}
	public boolean increment( ) {
		// dedicated adder circuit
		// assumes unsigned

		int i = toSignedInteger( );
		i = i + 1;
		cpu.datatypes.Integer value = new cpu.datatypes.Integer( i );  
		if( fromSignedInteger( value ) )
			return true;		// overflow
		return false;			// no overflow
	}
	/*
	public boolean increment( int n ) {
		// dedicated adder circuit
		// assumes unsigned

		int i = toJavaInt( );
		i = i + n;
		if( fromJavaInt( i ) )
			return true;		// overflow
		return false;			// no overflow
	}
	*/
	public boolean decrement( ) {
		// dedicated adder circuit
		// assumes unsigned

		int i = toJavaInt( );
		i = i - 1;
		if( fromJavaInt( i ) )
			return true;		// overflow
		return false;			// no overflow
	}
	private void twoscomplementinline( ) {
		// two's complement
		boolean carry = false;
		for( int i = 1; i < 16; i++ ) {
			if( !carry ) {
				if( bit( i ).value == true )
					carry = true;
			} else {
				bit( i ).value = !bit( i ).value;
			}
		}
	}
	private Word twoscomplement( ) {
		Word result = new Word( this );
		
		// two's complement
		boolean carry = false;
		for( int i = 1; i < 16; i++ ) {
			if( !carry ) {
				if( result.bit( i ).value == true )
					carry = true;
			} else {
				result.bit( i ).value = !result.bit( i ).value;
			}
		}
		return result;
	}
	public Word toWord( ) {
		Word word = new Word( );
		for( int i = 0; i < 16; i++ )
			word.bit( i ).value = bit( i ).value;
		
		return word;
	}
}
